// AVDecoder.cpp: implementation of the AVDecoder class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "AVDecoder.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

AVDecoder::AVDecoder() :
	m_vctx(0),
	m_actx(0),
	m_sctx(0),
	m_thread_count(1)
{

}

AVDecoder::~AVDecoder()
{
	Release();
}

void	AVDecoder::Release()
{
	if (m_vctx && m_vctx->codec) avcodec_close(m_vctx);
	if (m_actx && m_actx->codec) avcodec_close(m_actx);
	if (m_sctx && m_sctx->codec) avcodec_close(m_sctx);
	if (m_vctx) av_free(m_vctx); m_vctx = 0;
	if (m_actx) av_free(m_actx); m_actx = 0;
	if (m_sctx) av_free(m_sctx); m_sctx = 0;
	m_thread_count = 1;
}

INT32	AVDecoder::SetThreadCount(INT32 thread_count)
{
	m_thread_count = thread_count;
	return m_thread_count;
}

INT32	AVDecoder::SetContext(INT32 media_type, AVCodecContext* ctx)
{
	AVCodecContext* newctx = 0;
	AVCodec*		codec = 0;
	if (ctx)
	{
		newctx = avcodec_alloc_context();
		if (newctx)
		{
			if (avcodec_copy_context(newctx, ctx) == 0)
			{
				if (m_thread_count > 1)
//#if LIBAVFORMAT_VERSION_MAJOR < 55
//					avcodec_thread_init(newctx, m_thread_count);
//#else
					newctx->thread_count = m_thread_count;
//#endif
				codec = avcodec_find_decoder(newctx->codec_id);
				if (codec)
				{
					if (avcodec_open(newctx, codec) < 0)
					{
						goto copy_error;
					}
				}
				switch (media_type)
				{
				case AVMEDIA_TYPE_AUDIO:
					if (m_actx)
					{
						if (m_actx->codec) avcodec_close(m_actx);
						av_free(m_actx);
					}
					m_actx = newctx;					
					break;
				case AVMEDIA_TYPE_VIDEO:
					if (m_vctx)
					{
						if (m_vctx->codec) avcodec_close(m_vctx);
						av_free(m_vctx);
					}
					m_vctx = newctx;
					break;
				case AVMEDIA_TYPE_SUBTITLE:
					if (m_sctx)
					{
						if (m_sctx->codec) avcodec_close(m_sctx);
						av_free(m_sctx);
					}
					m_sctx = newctx;
					break;
				default:
					goto copy_error;
				}
			}
			else
			{
				goto copy_error;
			}
			return 1;
		}
		else
		{
			goto copy_error;
		}
		
	}
copy_error:
	if (newctx && newctx->codec) avcodec_close(newctx);
	if (newctx) av_free(newctx);
	return 0;
}

INT32	AVDecoder::CreateContext(INT32 media_type, INT32 codec_id, INT32 thread_count)
{
	AVCodecContext* newctx = avcodec_alloc_context();
	AVCodec*		codec = 0;
	if (newctx)
	{
		newctx->codec_type = (AVMediaType)media_type;
		if (thread_count > 1)
			newctx->thread_count = m_thread_count;
		codec = avcodec_find_decoder((CodecID)codec_id);
		if (codec)
		{
			if (avcodec_open(newctx, codec) < 0)
			{
				goto create_error;
			}
		}
		
		switch (media_type)
		{
		case AVMEDIA_TYPE_AUDIO:
			if (m_actx)
			{
				if (m_actx->codec) avcodec_close(m_actx);
				av_free(m_actx);
			}
			m_actx = newctx;					
			break;
		case AVMEDIA_TYPE_VIDEO:
			if (m_vctx)
			{
				if (m_vctx->codec) avcodec_close(m_vctx);
				av_free(m_vctx);
			}
			m_vctx = newctx;
			break;
		case AVMEDIA_TYPE_SUBTITLE:
			if (m_sctx)
			{
				if (m_sctx->codec) avcodec_close(m_sctx);
				av_free(m_sctx);
			}
			m_sctx = newctx;
			break;
		default:
			goto create_error;
		}
		return 1;
	}
create_error:
	if (newctx && newctx->codec) avcodec_close(newctx);
	if (newctx) av_free(newctx);
	return 0;
}

INT32	AVDecoder::SetFrame(INT32 media_type, AVPacket* avpkt, uint8_t* buffer, INT32 cbuffer, uint64_t* ppts, uint64_t* pdts)
{
	return 0;
}